package myTest;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.junit.Test;
import org.springframework.util.StopWatch;

import javax.sound.midi.Soundbank;
import java.lang.ref.PhantomReference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.WeakHashMap;
import java.util.concurrent.TimeUnit;
import java.util.stream.IntStream;

public class ReferenceTest {
    // 启动参数设置 -Xms7M -Xmx7M -Xlog:gc* 观察gc日志
    // 可输出为gc文件，并到 https://gceasy.io 进行分析查看

    public static void main(String[] args) throws InterruptedException {
        Student strongStudent = new Student("strong");
        WeakReference<Student> weakStudent = new WeakReference<>(new Student("weak"));
        SoftReference<Student> softStudent = new SoftReference<>(new Student("soft"));
        PhantomReference<Student> phantmoStudent = new PhantomReference<>(new Student("soft"), new ReferenceQueue<>());

        System.out.println(strongStudent);
        System.out.println(weakStudent.get());
        System.out.println(softStudent.get());
        System.out.println(phantmoStudent.get());

        fillMemory();
        System.out.println(strongStudent);
        System.out.println(weakStudent.get());
        System.out.println(softStudent.get());
        System.out.println(phantmoStudent.get());

    }

    @Test
    public void testReflect() {
        StopWatch stopWatch = new StopWatch();
        stopWatch.start("newInstance");
        IntStream.range(0, 100_0000).forEach(i -> {
            try {
                Student.class.getDeclaredConstructor().newInstance();
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            }
        });
        stopWatch.stop();
        stopWatch.start("new");
        IntStream.range(0, 100_0000).forEach(i -> {
            new Student();
        });
        stopWatch.stop();
        System.out.println(stopWatch.prettyPrint());
    }

    @Test
    public void weakHashMapTest() throws InterruptedException {
        Map<String, Student> weakMap = new WeakHashMap<>();
        weakMap.put("no1", new Student("no1"));
        weakMap.put(new String("no2"), new Student("no2"));
        String random = UUID.randomUUID().toString();
        weakMap.put(new String(random), new Student(random));
        weakMap.put(UUID.randomUUID().toString(), new Student("random"));
        weakMap.put(UUID.randomUUID().toString().intern(), new Student("random-intern"));

        System.out.println(weakMap.size());
        System.out.println(weakMap.get("no1"));
        System.out.println(weakMap.get("no2"));
        System.out.println(weakMap.get(random));
        System.out.println(weakMap);

        fillMemory();
        System.out.println(weakMap.size());
        System.out.println(weakMap.get("no1"));
        System.out.println(weakMap.get("no2"));
        System.out.println(weakMap.get(random));
        System.out.println(weakMap);

    }

    private static void fillMemory() throws InterruptedException {
        Map<String, Student> cache = new HashMap<>();
        IntStream.range(0, 6000).forEach(i -> {
            cache.put(String.valueOf(i), new Student(String.valueOf(i)));
        });
        System.gc();

        TimeUnit.SECONDS.sleep(1);
    }
}

@Data
@AllArgsConstructor
@NoArgsConstructor
class Student {
    private String name;
}
